package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import model.Classes;
import model.Day;
import model.TimeSlot;

/**
 * This Class will be the Panel in charge of 
 * organizing and displaying the cellsheet gui
 * of this scheduler that only allows a single
 * user to enter available hours information. 
 * 
 * @author Tristan D. Boucher
 * @version Commit #22 9/14/2013
 *
 */
@SuppressWarnings("serial")
public class GUIAvailabilityPanel extends AbstractView
{
  /**
   * Constant for Font point of the panels.
   */
  private static final int FONT_SIZE = 16;

  /**
   * Constant for Font for the text fields.
   */
  private static final int FIELD_FONT_SIZE = 12;

  /**
   * Width of this panel.
   */
  private static final int WIDTH = 900;

  /**
   * Height of this panel.
   */
  private static final int HEIGHT = 550;

  /**
   * The number of classes to be be displayed per row.
   */
  private static final int CLASSES_PER_ROW = 4;

  /**
   * The minimum number of hours a tutor can be scheduled a week.
   */
  private static final int MIN_WEEKLY_HOURS = 4;

  /**
   * The maximum number of hours a tutor can be scheuled a week.
   */
  private static final int MAX_WEEKLY_HOURS = 17;

  /**
   * The font color for the text in the cells.
   */
  private static final Color CELL_COLOR = Color.WHITE.darker();

  /**
   * This 2 dimmensional array holds and keeps track of all the
   * individual cells that a user may interact with.
   */
  private final AvailabilityCell[][] my_availability_cells;

  /**
   * This will hold the array for the classes.
   */
  private final Classes[] my_classes;

  /**
   * Constructor creates and populates the spreadsheet-like 
   * panel with JComboBoxes.
   * 
   * @param the_controller The controller object that this view
   * panel reports to.
   */
  public GUIAvailabilityPanel(final GUIController the_controller)
  {
    super(the_controller, WIDTH, HEIGHT);

    my_availability_cells = new AvailabilityCell[TimeSlot.getAllSlots().length]
        [Day.getDays().length];

    my_classes = Classes.getClasses().clone();

    addLinedBorder(addBackground(this, BACKGROUND_COLOR), LINED_BORDER_COLOR).
      setLayout(new BorderLayout());

    this.add(buildInstructionsPanel(), BorderLayout.NORTH);
    this.add(buildAvailabilityPanel(), BorderLayout.CENTER);
    this.add(buildClassesPanel(), BorderLayout.SOUTH);
    this.add(buildHoursSubmitPanel(), BorderLayout.EAST);
  }

  /**
   * This method is a helper method to clean up the constructor.
   * This method builds the Instructions for this view.
   * 
   * @return The panel containing the formatted instructions.
   */
  private JPanel buildInstructionsPanel()
  {
    final JPanel instructions = new JPanel();
    addBackground(instructions, BACKGROUND_COLOR);

    final JComponent temp_component = addTitledBorder(new JTextField(
        "Click on a cell to change color and " +
        "choosse the classes you are" +
        " able to tutor and click Submit." +
        "\n Key: Red = unavailable, Yellow = available, Green = preferred"),
        "Instructions", TEXT_FIELD_BORDER_COLOR, FIELD_FONT_SIZE); 
    instructions.add(addBackground(temp_component, BACKGROUND_COLOR));
    return instructions;
  }

  /**
   * This method is a helper method to clean up the constructor.
   * This method builds the panel manually using as many loops as possible.
   * 
   * @return The availability panel completely filled in.
   */
  private JPanel buildAvailabilityPanel()
  {
    final int days_length = Day.getDays().length;
    final int times_length = TimeSlot.getAllSlots().length;
    final JPanel availability_panel = new JPanel();

    availability_panel.setLayout(new GridLayout(TimeSlot.getAllSlots().length + 1, 
                                                Day.getDays().length + 1));
    addBackground(availability_panel, BACKGROUND_COLOR);
    availability_panel.add(addBackground(new JPanel(), BACKGROUND_COLOR));
    addLinedBorder(availability_panel, LINED_BORDER_COLOR);

    for (int i = 0; i < days_length; i++)
    {
      availability_panel.add(addBackground(new AvailabilityCell(Day.getDays()[i].toString(),
                                                                my_width,
                                                                my_height), 
                                                                BACKGROUND_COLOR));
    }

    for (int i = 0; i < times_length; i++)
    {
      availability_panel.add(addBackground(new AvailabilityCell(
                                                                TimeSlot.
                                                                getAllSlots()[i].toString(),
                                                                my_width,
                                                                my_height), 
                                                                BACKGROUND_COLOR));
      for (int j = 0; j < days_length; j++)
      {
        final AvailabilityCell temp_cell = 
            new AvailabilityCell(TimeSlot.getAllSlots()[i],
                                 Day.getDays()[j],
                                 my_width, 
                                 my_height);

        this.addTitledBorder(temp_cell, TimeSlot.getAllSlots()[i].toString(), 
                             CELL_COLOR, FONT_SIZE);
        availability_panel.add(temp_cell);
        my_availability_cells[i][j] = temp_cell;
      }
    }

    return availability_panel;
  }

  /**
   * Builds the panel that holds all the checkboxes for the classes one 
   * is available to tutor.
   * 
   * @return The panel with checkboxes on it that automatically update 
   * the classes they are attached to. 
   */
  private JPanel buildClassesPanel()
  {
    final JPanel classes_panel = new JPanel();
    final Classes[] classes = Classes.getClasses().clone();

    classes_panel.setLayout(new GridLayout(0, CLASSES_PER_ROW));

    for (int i = 0; i < Classes.getClasses().length; i++)
    {
      final ClassBox temp_box = new ClassBox(classes[i]);
      addBackground(temp_box, BACKGROUND_COLOR);

      temp_box.addActionListener(new ActionListener()
      {
        public void actionPerformed(final ActionEvent the_e)
        {
          if (the_e.getSource() instanceof ClassBox)
          {
            ((ClassBox) the_e.getSource()).
            my_class.setTutorable(((ClassBox) the_e.getSource()).isSelected());            
          }
        }
      });

      classes_panel.add(temp_box);
    }

    addLinedBorder(classes_panel, LINED_BORDER_COLOR);
    return classes_panel;
  }

  /**
   * Builds the panel that will house and deal with the entry of 
   * a minimum and maximum number of hours they wish to tutor a week
   * and will house the submit button.
   * 
   * @return The hoursSubmitPanel.
   */
  private JPanel buildHoursSubmitPanel()
  {
    final JPanel submit_panel = new JPanel();

    final JTextField min_hours_field = new JTextField("At least 4.");
    final JTextField max_hours_field = new JTextField("At most 17.");

    addLinedBorder(addBackground(submit_panel, BACKGROUND_COLOR), 
                    LINED_BORDER_COLOR);
    addTitledBorder(min_hours_field, "Min Weekly Hrs", 
                    TEXT_FIELD_BORDER_COLOR, FIELD_FONT_SIZE);
    addTitledBorder(max_hours_field, "Max Weekly Hrs",
                    TEXT_FIELD_BORDER_COLOR, FIELD_FONT_SIZE);

    min_hours_field.setBackground(BACKGROUND_COLOR);
    max_hours_field.setBackground(BACKGROUND_COLOR);

    final JButton submit_button = new JButton("Submit Availability");
    final JButton cancel_button = new JButton("Cancel Entry");

    addBackground(submit_button, BACKGROUND_COLOR);
    addBackground(cancel_button, BACKGROUND_COLOR);
    addLinedBorder(submit_button, LINED_BORDER_COLOR);
    addLinedBorder(cancel_button, LINED_BORDER_COLOR);
    
    submit_panel.setLayout(new GridLayout(0, 1));

    submit_button.addActionListener(new ActionListener()
    {
      public void actionPerformed(final ActionEvent the_e)
      {
        if (the_e.getSource() instanceof JButton)
        {
          try
          {
            if (Integer.parseInt(min_hours_field.getText().trim()) >= MIN_WEEKLY_HOURS &&
                Integer.parseInt(max_hours_field.getText().trim()) <= MAX_WEEKLY_HOURS)
            {
              final int[] min_max_hours = new int[2];
              min_max_hours[0] = Integer.parseInt(min_hours_field.getText().trim());
              min_max_hours[1] = Integer.parseInt(max_hours_field.getText().trim());

              my_controller.postAvailabilityEntry(my_availability_cells,
                                                  my_classes,
                                                  min_max_hours);
            }
          }
          catch (final NumberFormatException exception)
          {
            JOptionPane.showMessageDialog(GUIAvailabilityPanel.this,
                                          "Please enter an integer from " +
                                              "4 to 17 for the min and max hours.",
                                              "Error entering min/max Weekly Hours!",
                                              JOptionPane.ERROR_MESSAGE);
          }
        }
      }
    });

    cancel_button.addActionListener(new ActionListener()
    {
      public void actionPerformed(final ActionEvent the_e)
      {
        if (the_e.getSource() instanceof JButton)
        {
          my_controller.postLogout();
        }
      }
    });

    submit_panel.add(min_hours_field);
    submit_panel.add(max_hours_field);

    submit_panel.add(submit_button, BorderLayout.SOUTH);
    submit_panel.add(cancel_button, BorderLayout.SOUTH);

    return submit_panel;
  }

  /**
   * Returns all of the AvailabilityCell objects contained in this view.
   * 
   * @return All Availability in a 2d array.
   */
  public AvailabilityCell[][] getCells()
  {
    return my_availability_cells;
  }

  /**
   * Returns all the classes in this gui. They internally know if they 
   * are tutorable by this person or not.
   * 
   * @return All classes this tutor had to decide about.
   */
  public Classes[] getClasses()
  {
    return my_classes;
  }

  //Inner Classes
  /**
   * Special inner class that just improves upon the 
   * JCheckbox. It customizes it with a public field
   * that can be retrieved and modified easilly.
   * 
   * @author Tristan D. Boucher
   * @version 9/9/2013
   */
  final class ClassBox extends JCheckBox
  {
    /**
     * The class that will create this checkbox.
     */
    private final Classes my_class;

    /**
     * Constructor.
     * 
     * @param the_class The class used to construct this checkbox.
     */
    public ClassBox(final Classes the_class)
    {
      super(the_class.toString());
      my_class = the_class;
    }
  }
}
//End of class GUIAvailabilityPanel